﻿// ===================================
// <copyright>LogoUI Co.</copyright>
// <author>Vlad Spivak</author>
// <email>mailto:vlads@logoui.co.il</email>
// <created>21/00/10</created>
// <lastedit>Sunday, November 21, 2010</lastedit>

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//
// <remarks>Part of this software based on various internet sources, mostly on the works
// of members of Wpf Disciples group http://wpfdisciples.wordpress.com/
// Also project may contain code from the frameworks: 
//        Nito 
//        OpenLightGroup
//        nRoute
// </remarks>
// ====================================================================================//


#if SILVERLIGHT
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Interop;
using System.Windows.Media;

namespace LogoFX.Infra.Interactivity
{
    //todo:support for this list of cases
    //todo:currently only mousemove is supported
    public enum CloseTriggers
    {
        InsideClick,
        OutsideClick,
        AnyClick,
        MouseLeave,
        MouseMove
    }
    /// <summary>
    /// Propvides handling for popop closing, using underlying canvas events
    /// Opens popup full screen, put places its child on required coordinates
    /// </summary>
    public class AutoClosingPopupBehavior : Behavior<Popup>
    {

        #region Parent dependency property

        public Control Parent
        {
            get { return (Control)GetValue(ParentProperty); }
            set { SetValue(ParentProperty, value); }
        }

        public static readonly DependencyProperty ParentProperty =
            DependencyProperty.Register("Parent", typeof(Control), typeof(AutoClosingPopupBehavior), new PropertyMetadata(default(Control), OnParentChanged));

        private static void OnParentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        #endregion

        #region TriggerType dependency property

        public CloseTriggers TriggerType
        {
            get { return (CloseTriggers)GetValue(TriggerTypeProperty); }
            set { SetValue(TriggerTypeProperty, value); }
        }

        public static readonly DependencyProperty TriggerTypeProperty =
            DependencyProperty.Register("TriggerType", typeof(CloseTriggers), typeof(AutoClosingPopupBehavior), new PropertyMetadata(CloseTriggers.MouseMove, OnTriggerTypeChanged));

        private static void OnTriggerTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        #endregion

        private Canvas OutsidePopupCanvas { get; set; }

        private Canvas PopupChildCanvas { get; set; }

        private FrameworkElement PopupChild { get; set; }

        protected override void OnAttached()
        {
            AssociatedObject.Loaded += BuildStructure;
            base.OnAttached();
        }

        private void BuildStructure(object n, object o)
        {
            PopupChild = AssociatedObject.Child as FrameworkElement;
            if (PopupChild != null)
            {
                PopupChildCanvas = new Canvas();
                AssociatedObject.Child = PopupChildCanvas;

                OutsidePopupCanvas = new Canvas();
                OutsidePopupCanvas.Background = new SolidColorBrush(Colors.Transparent);

                //if(TriggerType == CloseTriggers.OutsideClick)
                OutsidePopupCanvas.MouseLeftButtonDown += OutsidePopup_MouseLeftButtonDown;
                OutsidePopupCanvas.MouseMove += OutsidePopup_MouseMove;

                PopupChildCanvas.Children.Add(OutsidePopupCanvas);
                PopupChildCanvas.Children.Add(PopupChild);
                PopupChild.SizeChanged += PopupChild_SizeChanged;

                //PopupChild.GotFocus += PopupChild_GotFocus;
                //PopupChild.LostFocus += PopupChild_LostFocus;
                //PopupChild.MouseEnter += PopupChild_MouseEnter;
                //PopupChild.MouseLeave += PopupChild_MouseLeave;
                //PopupChild.SizeChanged += PopupChild_SizeChanged;
            }

        }

        private void PopupChild_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Arrange();
        }

        private void Arrange()
        {
            if (PopupChild == null || Application.Current == null || OutsidePopupCanvas == null)
            {
                return;
            }
            Content hostContent = Application.Current.Host.Content;
            double rootWidth = hostContent.ActualWidth;
            double rootHeight = hostContent.ActualHeight;

            double popupContentWidth = PopupChild.ActualWidth;



            MatrixTransform mt = AssociatedObject.TransformToVisual(null) as MatrixTransform;
            double rootOffsetX = mt.Matrix.OffsetX;
            double rootOffsetY = mt.Matrix.OffsetY;

            OutsidePopupCanvas.Width = rootWidth;
            OutsidePopupCanvas.Height = rootHeight;
            PopupChild.MaxWidth = rootWidth;
            PopupChild.MinHeight = 0;

            PopupChild.Width = popupContentWidth;
            PopupChild.HorizontalAlignment = HorizontalAlignment.Left;
            PopupChild.VerticalAlignment = VerticalAlignment.Top;

            // Set the top left corner for the actual drop down.
            AssociatedObject.HorizontalOffset = -rootOffsetX;
            AssociatedObject.VerticalOffset = -rootOffsetY;
            Canvas.SetLeft(PopupChild, rootOffsetX);
            Canvas.SetTop(PopupChild, rootOffsetY);

        }

        private void OutsidePopup_MouseMove(object sender, MouseEventArgs e)
        {
            AssociatedObject.IsOpen = false;
        }

        private void OutsidePopup_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            AssociatedObject.IsOpen = false;
        }

        protected override void OnDetaching()
        {
            AssociatedObject.Loaded -= BuildStructure;
            if (PopupChild != null)
            {
                OutsidePopupCanvas.MouseLeftButtonDown -= OutsidePopup_MouseLeftButtonDown;
                OutsidePopupCanvas.MouseMove -= OutsidePopup_MouseMove;
                PopupChild.SizeChanged -= PopupChild_SizeChanged;
            }


            base.OnDetaching();
        }

    }
}
#endif